<!doctype html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <link rel="shortcut icon" href="/favicon.ico" />
    <link href="/app/ai/css/bootstrap.min.css?v=5.3" rel="stylesheet">
    <link href="/app/ai/css/app.css?v=<?=ai_css_version()?>" rel="stylesheet">
    <script src="/app/ai/js/jquery.min.js"></script>
    <script src="/app/ai/js/bootstrap.bundle.min.js?v=5.3"></script>
    <title>webman AI - 图片广场</title>
</head>

<body data-bs-theme="light">
<div id="app" class="h-100">
    <div class="header d-flex justify-content-between"><span>图片广场</span> <b class="iconfont" @click.stop="showOptions=!showOptions">&#xe9f8;</b></div>
    <div class="overflow-scroll p-sm-1" style="height: calc(100% - 45px);" @scroll.passive="handleScroll">
        <div ref="imageBox" :style="'padding-left:'+boxMarginLeft+'px'" class="h-100">
            <div class="box h-100" :class="{empty:!images.length}">
                <div v-for="(image,index) in images" @mouseover="hoverId=image.id" @mouseout="hoverId=null" class="card border-0 item position-absolute shadow-sm" :style="{top: image.top + 'px', left: image.left + 'px', width:imgWidth + 'px'}">
                    <img :src="image.thumb_url" class="card-img-top" alt="" @click="previewImage(image.image_url)">
                    <div class="card-body">
                        <div class="card-title text-truncate">{{image.prompt}}</div>
                        <div class="text-secondary-sm text-truncate" style="width: calc(100% - 20px)">
                            <span class="text-truncate d-inline-block" style="max-width:150px">{{image.user?image.user.nickname:'匿名'}}</span>
                            <span class="d-inline-block text-truncate"><span class="px-1">·</span>{{formatDate(image.created_at)}}</span>
                        </div>
                        <span v-show="hoverId===image.id||isMobile" @click="draw(image.image)" title="画同款" class="icon-btn-secondary cursor-pointer icon-gallery-fill f22 position-absolute" style="bottom: 0.3rem;right: 0.7rem;"></span>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- 顶部右侧菜单 -->
    <div class="top-right-options-box shadow-sm border-top rounded" style="z-index:10000" v-show="showOptions" :class="{'slide-up':showOptions}">
        <a class="dropdown-item py-2 px-4 cursor-pointer" @click="reload()">刷新</a>
    </div>
</div>

<!-- vue -->
<script type="text/javascript" src="/app/ai/js/vue.global.js"></script>

<script>
    const App = {
        data() {
            return {
                limit: 20,
                end: false,
                loading: false,
                imgWidth: 256,
                gapWidth: 10,
                promptBoxHeight: 80,
                boxMarginLeft: 0,
                images: [],
                columns: [],
                isMobile: false,
                lastId: 2147483647,
                hoverId: null,
                showOptions: false,
            };
        },
        mounted() {
            this.fetchImages();
            // 监听resize
            window.addEventListener('resize', () => {
                const len = Math.floor((this.$refs.imageBox.offsetWidth + this.gapWidth) / (this.imgWidth + this.gapWidth));
                this.boxMarginLeft = (this.$refs.imageBox.offsetWidth + this.gapWidth - len * (this.imgWidth + this.gapWidth)) / 2;
                this.checkMobile();
                if (len !== this.columns.length || this.isMobile) {
                    this.columns = [];
                    this.appendImages([]);
                }
            });
            this.checkMobile();
        },
        methods: {
            checkMobile() {
                this.isMobile = parent.ai.isMobile;
                this.imgWidth = this.isMobile ? Math.max(120, Math.min(Math.floor((parent.innerWidth - 20 + this.gapWidth) / 2 - this.gapWidth), 256)) : 256;
                this.limit = this.isMobile ? 6 : 20;
            },
            fetchImages() {
                if (this.end || this.loading) return;
                this.loading = true;
                $.ajax({
                    url: '/app/ai/gallery/images',
                    type: 'GET',
                    data: {id: this.lastId, limit: this.limit},
                    success: (res) => {
                        const { data: { items } } = res;
                        if (items && items.length) {
                            this.lastId = items[items.length - 1].id;
                            this.appendImages(items);
                        }
                        if (items.length < this.limit) {
                            this.end = true;
                        }
                    },
                    complete: () => {
                        this.loading = false;
                    }
                });
            },
            appendImages(images) {
                if (!this.columns.length) {
                    const len = Math.floor((this.$refs.imageBox.offsetWidth + this.gapWidth) / (this.imgWidth + this.gapWidth));
                    this.boxMarginLeft = (this.$refs.imageBox.offsetWidth + this.gapWidth - len * (this.imgWidth + this.gapWidth)) / 2;
                    this.columns = new Array(len).fill(0);
                    images = this.images ? this.images.concat(images) : images;
                    this.images = [];
                }
                for (let item of images) {
                    if (!item.thumb_url) continue;
                    let image = new Image();
                    image.src = item.thumb_url;
                    image.onload = () => {
                        let height = (image.height / image.width) * this.imgWidth + this.promptBoxHeight;
                        let minIndex = 0;
                        let minHeight = this.columns[0] || 0;
                        for (let i = 0; i < this.columns.length; i++) {
                            if (this.columns[i] < minHeight) {
                                minHeight = this.columns[i];
                                minIndex = i;
                            }
                        }
                        this.columns[minIndex] += height + this.gapWidth;
                        this.images.push({
                            ...item,
                            top: minHeight + this.gapWidth,
                            left: minIndex * (this.imgWidth + this.gapWidth),
                        });
                    }
                }
            },
            handleScroll(event) {
                const div = event.target;
                if (div.scrollHeight - div.scrollTop - div.clientHeight < 20) {
                    this.fetchImages();
                }
            },
            previewImage(url) {
                window.parent.ai.previewImage(url);
            },
            draw(image) {
                const module = image.module || "painting";
                window.parent.ai.switchModule(module, function() {
                    window.parent.$("#" + module)[0].contentWindow[module].importImage(image);
                });
                try {
                    window.parent.$("#" + module)[0].contentWindow[module].importImage(image);
                } catch (e){}
            },
            formatDate(date) {
                return window.parent.ai.formatDate(date);
            },
            reload() {
                this.images = [];
                this.columns = [];
                this.end = false;
                this.lastId = 2147483647;
                this.fetchImages();
            }
        }
    }
    gallary = Vue.createApp(App).mount('#app');

    $(document).click(function () {
        try {window.parent.ai.hideAll();} catch (e) {}
        gallary.showOptions = false;
    });

    try {
        $(document.body).attr("data-bs-theme", window.parent.ai.theme);
        parent.ai.showIframe();
    } catch (e) {}
</script>


<style>
    .box {
        position: relative;
        box-sizing: border-box;
    }
    .box img {
        vertical-align: top;
    }
    .p-sm-1 {
        padding-left: 10px;
        padding-right: 10px;
    }
    .card-body {
        height: 80px;
    }
    .card {
        background: var(--ai-white-bg);
    }
</style>
</body>
</html>
